
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include "ca2fw.h"
#include "task.h"

struct my_q //The structure for system message queue which is used as a buffer for the incoming requests
{
    long mtype;
    REQUEST req;
};

int qid1, qid2; //queue identifiers
struct my_q write_q; //The write buffer
struct my_q read_q1, read_q2; //The read buffer
key_t key; //Message Queue ID
key_t key1; //Message Queue Key
int empty1 = 0;
int empty2 = 0;

void read_Requestdb1(void* ptr);
void read_Requestdb2(void* ptr);
void write_Request(void* ptr);


void write_Request(void* ptr)
{
//start the framework
 startFramework();
    while (!noMoreRequests())
    {
        if (isRequestAvailable() == 1)
         {
            write_q.req = getRequest();
            if (getDB(write_q.req) == 1)
            {

                     msgsnd(qid1, &write_q, sizeof (REQUEST), IPC_NOWAIT);
                }
              else //Push incoming packets to the queue for db2
                {
                    if (msgsnd(qid2, &write_q, sizeof (REQUEST), IPC_NOWAIT) == -1)
                        perror("msgsnd error");
                }
            }
            taskdelay(1);
    }
    taskdelay(1);
    while(empty1==0 || empty2==0)//Checking for the queue to be empty
        taskdelay(1);
        stopFramework(); //stop framework
}

//Function to read requests form the queue for db1

void read_Requestdb1(void* ptr)
{
    while (!noMoreRequests() || empty1==0)
    {
        if (msgrcv(qid1, &read_q1, sizeof (REQUEST), 1, IPC_NOWAIT) == -1)
        {
            taskdelay(1); //Read the request from the queue
            empty1 = 1;
        }
        else
        {
            empty1 = 0;
            int db = getDB(read_q1.req); //Get the db number
            int feed = getFeed(read_q1.req); //Get the feed number
            RESPONSE rsp;
            MSISDN user = getUser(read_q1.req);
            if (db == 1)
            {
                if (requestData(db, feed) == OK)
                {

                    do {
                        rsp = getRequestedData(db);
                        taskdelay(1);
                       } while (rsp == BUSY);
                    sendResponse(user, rsp);
                }

            }
        }
        taskdelay(1);
    }
}



//Function to read requests form the queue for db1

void read_Requestdb2(void* ptr)
{

    while (!noMoreRequests() || empty2==0)
    {
        if (msgrcv(qid2, &read_q2, sizeof (REQUEST), 1, IPC_NOWAIT) == -1)
        {
            taskdelay(1);
            empty2 = 1;
        }
        else
        {
            empty2 =0;
            int db = getDB(read_q2.req);
            int feed = getFeed(read_q2.req);
            RESPONSE rsp;
            MSISDN user = getUser(read_q2.req);
            if (db == 2)
            {
                if (requestData(db, feed) == OK)
                {

                    do {
                        rsp = getRequestedData(db);
                        taskdelay(1);
                    } while (rsp == BUSY);
                    sendResponse(user, rsp);
                }
            }
        }
        taskdelay(1);
    }
}

//Main Program

void taskmain(int argc, char** argv)
{
    if ((key = ftok("caa2.c", 'b')) == -1) //creating the key for the queue
    {
        perror("ftok");
        exit(1);
    }
    msgctl(qid1, IPC_SET, NULL);
    qid1 = msgget(key, 0644 | IPC_CREAT);
    if (qid1== -1) //creating the system queue
    {
        perror("msgget");
        exit(1);
    }

    if ((key1 = ftok("caa2.c", 'c')) == -1)
    {
        perror("ftok");
        exit(1);
    }
    msgctl(qid2, IPC_SET, NULL);
    qid2 = msgget(key1, 0644 | IPC_CREAT);
    if( qid2 == -1)
    {
        perror("msgget");
        exit(1);

    }
    write_q.mtype = 1;
    taskcreate(&write_Request, NULL, 32768);    //task created for to write request in the queue
    taskcreate(&read_Requestdb1, NULL, 32768);  //task created to read request from db1
    taskcreate(&read_Requestdb2, NULL, 32768);  //task created to read request from db2
}

